#include <QApplication>
#include <QtCore/QCoreApplication>
#include <QMainWindow>
#include <QPointF>
#include <vector>
#include <QVector>

#include "glwidget.h"
#include "Bezier/bezier.h"
#include "Bezier/rbezier.h"
#include "Bezier/bezierspline.h"
#include "BSpline/bspline.h"
#include "BSpline/nurbs.h"
#include "NS/ncs.h"

int main(int argc, char *argv[])
{
//    //QCoreApplication a( argc, argv );
    QApplication app( argc, argv );

    curveLib::bezier::Bezier< QPointF > b;
    b.AddPoint( QPointF( 0.0, 0.0 ) );
    b.AddPoint( QPointF( 30.0, 70.0 ) );
    b.AddPoint( QPointF( 70.0, 110.0 ) );
    b.AddPoint( QPointF( 200.0, 200.0 ) );

    //curveLib::bezier::Bezier< QPointF >* bsplit = b.Split( 0.5 );

    curveLib::bezier::Bezier< QPointF > be = b;
    be.ElevateDegree( 3 );
    be.Move( QPointF( 50.0, 0.0 ) );

    curveLib::bezier::Bezier< QPointF > redbe = be;
    redbe.ReduceDegree( 3, curveLib::bezier::Bezier< QPointF >::Simple );
    redbe.Move( QPointF( 50.0, 0.0 ) );

    curveLib::bezier::RBezier< QPointF > rb;
    rb.AddPoint( QPointF( 0.0, 0.0 ), 2.0 );
    rb.AddPoint( QPointF( 300.0, 100.0 ), 1.5 );
    rb.AddPoint( QPointF( 200.0, 400.0 ), 3.0 );
    rb.AddPoint( QPointF( 50.0, 50.0 ), 0.3 );
    rb.Move( QPointF( 150.0, 100.0 ) );
    rb.Scale( 0.8 );
    rb.Close( );

    curveLib::bezier::RBezier< QPointF > rbe = rb;
    rbe.ElevateDegree( 7 );
    //rbe.Move( QPointF( 50.0, 0.0 ) );

    //curveLib::bezier::RBezier< QPointF >* rbsplit = rb.Split( 0.5 );

    curveLib::bSpline::BSpline< QPointF > bs1( 3 );
    bs1.AddPoint( QPointF( 0.0, 0.0 ) );
    bs1.AddPoint( QPointF( 30.0, 70.0 ) );
    bs1.AddPoint( QPointF( 70.0, 110.0 ) );
    bs1.AddPoint( QPointF( 200.0, 200.0 ) );
    bs1.AddPoint( QPointF( 300.0, 250.0 ) );
    bs1.Move( QPointF( 100.0, 100.0 ) );
    bs1.SetInterpolationTypeFlags( curveLib::bSpline::IBSpline::First |
                                   curveLib::bSpline::IBSpline::Last );
    curveLib::bSpline::BSpline< QPointF > bs2 = bs1;
    bs2.RemovePoint( 0 );
    bs2.RemovePoint( 2 );
    bs2.RemovePoint( 1 );
    bs2.RemovePoint( 0 );
//    bs2.RemovePoint( );
//    bs2.RemovePoint( );
//    bs2.RemovePoint( );
//    bs2.RemovePoint( );
//    bs2.RemovePoint( );
//    bs2.AddPoint( QPointF( 0.0, 0.0 ) );
    bs2.AddPoint( QPointF( 30.0, 70.0 ) );
//    bs2.AddPoint( QPointF( 70.0, 110.0 ) );
    bs2.AddPoint( QPointF( 200.0, 200.0 ) );
//    bs2.AddPoint( QPointF( 300.0, 250.0 ) );
//    bs2.Move( QPointF( 150.0, 100.0 ) );

    bs2.Update( );

    curveLib::bSpline::NURBS< QPointF > nurbs1( 3 );
    nurbs1.AddPoint( QPointF( 0.0, 0.0 ), 1.0 );
    nurbs1.AddPoint( QPointF( 30.0, 70.0 ), 1.0 );
    nurbs1.AddPoint( QPointF( 70.0, 110.0 ), 1.0 );
    nurbs1.AddPoint( QPointF( 200.0, 200.0 ), 1.0 );
    nurbs1.AddPoint( QPointF( 300.0, 250.0 ), 1.0 );
    nurbs1.SetInterpolationTypeFlags( curveLib::bSpline::IBSpline::None |
                                      curveLib::bSpline::IBSpline::First |
                                      curveLib::bSpline::IBSpline::Last );
    nurbs1.RemovePoint( );


    curveLib::ICurve< QPointF >* ic = new curveLib::bSpline::BSpline< QPointF >( 3 );
    ic->GetCurvePoints( );

    curveLib::ns::NCS< QPointF > ncs1;
    ncs1.AddPoint( QPointF( 40.0, 40.0 ) );
    ncs1.AddPoint( QPointF( 30.0, 70.0 ) );
    /*ncs1.AddPoint( QPointF( 70.0, 110.0 ) );
    ncs1.AddPoint( QPointF( 200.0, 200.0 ) );
    ncs1.AddPoint( QPointF( 130.0, 70.0 ) );*/
    ncs1.Move( QPointF( 100.0, 100.0 ) );

    curveLib::bezier::RBezier< QPointF > circle;
    circle.AddPoint( QPointF( 0.0, 0.0 ) );
    circle.AddPoint( QPointF( 40.0, 0.0 ), 0.2 );
    circle.AddPoint( QPointF( 20.0, 40.0 ), 0.2 );
    circle.AddPoint( QPointF( -20.0, 40.0 ), 0.2 );
    circle.AddPoint( QPointF( -40.0, 0.0 ), 0.2 );
    circle.AddPoint( QPointF( 0.0, 0.0 ) );
    circle.Move( QPointF( 100.0, 100.0 ) );
    circle.Scale( -2.0 );

    curveLib::bezier::RBezier< QPointF, QVector< QPointF > >* circlePtr =
            new curveLib::bezier::RBezier< QPointF, QVector< QPointF > >( );
    circlePtr -> MakeCircle( );
    circlePtr -> Scale( 3.0 );
    circlePtr -> Move( QPointF( 200.0, 200.0 ) );
    circlePtr -> Rotate( 90.0 );
    circlePtr -> GetConvexHull( );

    curveLib::bezier::BezierSpline< QPointF > bezierSpline;
    bezierSpline.AddPoint( QPointF( 300.0, 100.0 ) );
    bezierSpline.AddPoint( QPointF( 100.0, 200.0 ) );
//    bezierSpline.AddPoint( QPointF( 200.0, 150.0 ) );
//    bezierSpline.AddPoint( QPointF( 300.0, 350.0 ) );
//    bezierSpline.MovePoint( 0, QPointF( -50.0, 0.0 ) );
    bezierSpline.SetPointPosition( 0, QPointF( 300.0, 110.0 ) );
    bezierSpline.SetPointPosition( 0, QPointF( 300.0, 150.0 ) );
    bezierSpline.SetPointPosition( 0, QPointF( 300.0, 200.0 ) );
    bezierSpline.SetPointPosition( 0, QPointF( 300.0, 250.0 ) );
    bezierSpline.SetPointPosition( 0, QPointF( 300.0, 300.0 ) );

    curveLib::bezier::Bezier< QPointF > bez1;
    bez1.AddPoint( QPointF( 100.0, 100.0 ) );
    bez1.AddPoint( QPointF( 150.0, 150.0 ) );
    bez1.AddPoint( QPointF( 200.0, 170.0 ) );
    bez1.AddPoint( QPointF( 220.0, 120.0 ) );
    curveLib::bezier::Bezier< QPointF > bez2;
    bez2.AddPoint( QPointF( 100.0, 100.0 ) );
    bez2.AddPoint( QPointF( 150.0, 150.0 ) );
    bez2.AddPoint( QPointF( 200.0, 170.0 ) );
    bez2.AddPoint( QPointF( 220.0, 120.0 ) );
    bez2.Move( QPointF( 0.0, 200.0 ) );
//    bez2.Close( );
    curveLib::bezier::Bezier< QPointF > bez3;
    bez3.AddPoint( QPointF( 120.0, 90.0 ) );
    bez3.AddPoint( QPointF( 320.0, 120.0 ) );
    bez3.AddPoint( QPointF( 20.0 , 40.0 ) );
    bez3.AddPoint( QPointF( 260.0, 300.0 ) );
    bez3.AddPoint( QPointF( 190.0, 220.0 ) );
    bez3.Move( QPointF( 100.0, 0.0 ) );
//    bez3.Close( );
    curveLib::bezier::Bezier< QPointF > bez4;
    bez4.AddPoint( QPointF( 120.0, 90.0 ) );
    bez4.AddPoint( QPointF( 320.0, 120.0 ) );
    bez4.AddPoint( QPointF( 20.0 , 40.0 ) );
    bez4.AddPoint( QPointF( 260.0, 300.0 ) );
    bez4.AddPoint( QPointF( 190.0, 220.0 ) );
    bez4.Move( QPointF( 100.0, 200.0 ) );
//    bez4.Close( );

    bez1.Join( bez3, curveLib::bezier::Bezier< QPointF >::C2 );
//    bez2.Join( bez4, curveLib::bezier::Bezier< QPointF >::C2 );
//    bez1.Close( );
//    bez3.Close( );

    GLWidget* glWidget = new GLWidget( );
    glWidget -> AddCurve( &ncs1, QColor( 0, 0, 0 ), QColor( 0, 0, 0 ) );
//    glWidget -> AddCurve( &bs1, QColor( 0, 0, 0 ), QColor( 0, 0, 0 ) );
//    glWidget -> AddCurve( &bs2, QColor( 0, 0, 255 ), QColor( 0, 0, 255 ) );
    //glWidget -> AddCurve( &nurbs1, QColor( 0, 0, 255 ), QColor( 0, 0, 255 ) );
    //glWidget -> AddCurve( &b, QColor( 0, 0, 0 ), QColor( 0, 0, 0 ) );
    //glWidget -> AddCurve( &be, QColor( 0, 0, 255 ), QColor( 0, 0, 255 ) );
    //glWidget -> AddCurve( &redbe, QColor( 0, 0, 255 ), QColor( 0, 0, 255 ) );
//    glWidget -> AddCurve( &rb, QColor( 255, 0, 0 ), QColor( 255, 0, 0 ) );
    //glWidget -> AddCurve( &rbe, QColor( 0, 255, 255 ), QColor( 0, 255, 255 ) );
    //glWidget -> AddCurve( bsplit, QColor( 0, 255, 0 ), QColor( 0, 255, 0 ) );
    //glWidget -> AddCurve( rbsplit, QColor( 0, 0, 255 ), QColor( 0, 0, 255 ) );
//    glWidget -> AddCurve( &circle, QColor( 0, 0, 0 ), QColor( 0, 0, 0 ) );
    //glWidget -> AddCurve( circlePtr, QColor( 0, 0, 0 ), QColor( 0, 0, 0 ) );
//    glWidget -> AddCurve( &bezierSpline, QColor( 0, 0, 0 ), QColor( 0, 0, 0 ) );
//    glWidget -> AddCurve( &bez1, QColor( 255, 0, 0 ), QColor( 255, 0, 0 ) );
//    glWidget -> AddCurve( &bez2, QColor( 0, 255, 0 ), QColor( 0, 255, 0 ) );
//    glWidget -> AddCurve( &bez3, QColor( 0, 0, 255 ), QColor( 0, 0, 255 ) );
//    glWidget -> AddCurve( &bez4, QColor( 255, 0, 255 ), QColor( 255, 0, 255 ) );

    QMainWindow mainWindow;
    mainWindow.setCentralWidget( glWidget );
    mainWindow.show( );

//    //return a.exec( );
    return app.exec( );
}
